﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace HcEncodec.Sdk
{
    /// <summary>
    /// PlayCtrl
    /// </summary>
    public sealed class PlayCtrl
    {
        public const string PLAYM4_API = "extern \"C\"__declspec(dllexport)";

        #region Struct

        public struct FRAME_INFO
        {
            ///<summary>
            ///画面宽，单位像素。如果是音频数据则为音频声道数；
            /// long nwidth;
            ///</sumary>
            public int nWidth;
            ///<summary>
            ///画面高。如果是音频数据则为样位率；
            /// long nHeight;
            ///</summary>
            public int nHeight;
            ///<summary>
            ///时标信息，单位毫秒。
            /// long nStamp;
            ///</summary>
            public int nStamp;
            ///<summary>
            ///数据类型，T_AUDIO16，T_RGB32，T_YV12
            /// long nType;
            ///</summary>
            public int nType;
            ///<summary>
            ///编码时产生的图像帧率，如果是音频数据则为采样率 
            /// long nFrameRate;
            ///</summary>
            public int nFrameRate;
            /// <summary>
            /// 帧号
            /// </summary>
            public int dwFrameNum;
        }

        public struct PFRAME_POS
        {
            ///<summary>
            ///出错的文件位置
            /// long nFilePos;
            ///</summary>
            public int nFilePos;
            ///<summary>
            ///出错后正常的帧号
            /// long nFrameNum;
            ///</summary>
            public int nFrameNum;
            ///<summary>
            ///出错后正常的时间(相对此文件开始时间)
            /// long nFrameTime;
            ///</summary>
            public int nFrameTime;
            ///<summary>
            ///出错时的帧号
            ///long nErrorFrameNum;
            ///</summary>
            public int nErrorFrameNum;
            ///<summary>
            ///出错的绝对时间(设备录象文件有用)
            ///SYSTEMTIME *pErrorTime;
            ///</summary>
            public IntPtr pErrorTime;
            ///<summary>
            ///出错时丢失的帧数
            /// long nErrorLostFrameNum;
            ///</summary>
            public int nErrorLostFrameNum;
            ///<summary>
            ///出错时错误的数据大小
            /// long nErrorFrameSize;
            ///</summary>
            public int nErrorFrameSize;

            /// <summary>
            /// 
            /// </summary>
            public void Init()
            {
                nFilePos = 0;
                nFrameNum = 0;
                nFrameTime = 0;
                nErrorFrameNum = 0;
                pErrorTime = new IntPtr();
                nErrorLostFrameNum = 0;
                nErrorFrameSize = 0;
            }
        }

        public struct FRAME_TYPE
        {
            ///<summary>
            ///数据帧首地址
            ///char *pDataBuf:
            ///</sumary>
            [MarshalAsAttribute(UnmanagedType.LPStr)]
            public string pDataBuf;
            ///<summary>
            ///数据帧的大小
            /// long nSize;
            ///</summary>
            public int nSize;
            ///<summary>
            ///数据帧的个数
            /// long nFrameNum;
            ///</sumary>
            public int nFrameNum;
            ///<summary>
            ///是否音频帧
            ///B00L bIsAudio;
            ///</summary>
            public bool bIsAudio;
            ///<summary>
            ///保留
            /// long nReserved;
            ///</summary>
            public int nReserved;

            public void Init()
            {
                pDataBuf = "";
                nSize = 0;
                nFrameNum = 0;
                bIsAudio = false;
                nReserved = 0;
            }
        }

        #endregion;

        #region Delegate

        public delegate void DecCBFun(int nPort, IntPtr pBuf, int nSize, ref FRAME_INFO pFrameInfo, int nReserved1, int nReserved2);

        public delegate void DisplayCBFun(int nPort, IntPtr pBuf, int nSize, int nWidth, int nHeight, int nStamp, int nType, int nReserved);

        public delegate void FileEndCallback(int nPort, int nReserved);

        #endregion

        #region Const Member Variables        
        // #define WINVER         
        // 0x0700 Windows 7        
        // 0x0600 Windows Vista        
        // 0x0502 Windows 2003 Server        
        // 0x0410 Windows XP        
        // 0x0400 Windows 98/Windows 2000        
        public static readonly int WINVER = 0x0502;
        public static readonly uint WM_USER = 0x0400;
        public static readonly uint WM_FILE_END = WM_USER + 33;
        public static readonly uint WM_ENC_CHANGE = WM_USER + 100;
        public static readonly int COLOR_DEFAULT = 64;
        public static readonly int PLAYER_SLIDER_MAX = 200;
        public static readonly int MAX_DISPLAY_DEVICE = 4;
        public static readonly int WIDTH_PAL = 352;
        public static readonly int HEIGHT_PAL = 288;

        #region Source buffer        
        public static readonly uint SOURCE_BUF_MAX = 1024 * 100000;//#define SOURCE_BUF_MAX     
        public static readonly uint SOURCE_BUF_MIN = 1024 * 50; //#define SOURCE_BUF_MIN    1024*50
        #endregion

        #region Frame type   
        public static readonly int T_AUDIO16 = 101;//音频数据;采样率16khz，单声道，每个采样点16位表示。
        public static readonly int T_AUDIO8 = 100;
        public static readonly int T_UYVY = 1; //视频数据，uyvy格式。“U0-Y0-V0-Y1-U2-Y2-V2-Y3….”，第一个像素位于图像左上角。
        public static readonly int T_YV12 = 3; //视频数据，yv12格式。排列顺序“Y0-Y1-……”，“V0-V1….”，“U0-U1-…..”        
        public static readonly int T_RGB32 = 7;//视频数据。每个像素4个字节，排列方式与位图相似，“B-G-R-0 ……”，第一个像素位于图像左下角。      

        #endregion

        #region Stream type  
        public static readonly int STREAME_REALTIME = 0;//实时模式，适合播放网络实时数据，解码器会立刻解码
        public static readonly int STREAME_FILE = 1; //文件模式，适合用户把文件数据用流方式输入。  注意：当PlayM4_InputData()返回FALSE时，用户要等一下重新输入
        #endregion

        #region Error code        
        public static readonly int PLAYM4_NOERROR = 0; //没有错误；
        public static readonly int PLAYM4_PARA_OVER = 1; //输入参数非法；
        public static readonly int PLAYM4_ORDER_ERROR = 2; //调用顺序不对；
        public static readonly int PLAYM4_TIMER_ERROR = 3; //多媒体时钟设置失败；
        public static readonly int PLAYM4_DEC_VIDEO_ERROR = 4; //视频解码失败；
        public static readonly int PLAYM4_DEC_AUDIO_ERROR = 5; //音频解码失败；
        public static readonly int PLAYM4_ALLOC_MEMORY_ERROR = 6; //分配内存失败；
        public static readonly int PLAYM4_OPEN_FILE_ERROR = 7; //文件操作失败；
        public static readonly int PLAYM4_CREATE_OBJ_ERROR = 8; //创建线程事件等失败；
        public static readonly int PLAYM4_CREATE_DDRAW_ERROR = 9; //创建DierctDraw失败；
        public static readonly int PLAYM4_CREATE_OFFSCREEN_ERROR = 10; //创建后端缓存失败；
        public static readonly int PLAYM4_BUF_OVER = 11; //缓冲区满，输入流失败；
        public static readonly int PLAYM4_CREATE_SOUND_ERROR = 12; //创建音频设备失败；
        public static readonly int PLAYM4_SET_VOLUME_ERROR = 13; //设置音量失败；
        public static readonly int PLAYM4_SUPPORT_FILE_ONLY = 14; //只能在播放文件时才能使用此接口；
        public static readonly int PLAYM4_SUPPORT_STREAM_ONLY = 15; //只能在播放流时才能使用此接口；
        public static readonly int PLAYM4_SYS_NOT_SUPPORT = 16; //不支持；
        public static readonly int PLAYM4_FILEHEADER_UNKNOWN = 17; //没有文件头；
        public static readonly int PLAYM4_VERSION_INCORRECT = 18; //解码器和编码器版本不对应；
        public static readonly int PALYM4_INIT_DECODER_ERROR = 19; //初始化解码器失败；
        public static readonly int PLAYM4_CHECK_FILE_ERROR = 20; //文件太短或码流无法识别；
        public static readonly int PLAYM4_INIT_TIMER_ERROR = 21; //初始化多媒体时钟失败；
        public static readonly int PLAYM4_BLT_ERROR = 22; //位拷贝失败(32位播放库下容易出现此问题，主要是渲染创建失败）；
        public static readonly int PLAYM4_UPDATE_ERROR = 23; //显示overlay失败；
        public static readonly int PLAYM4_OPEN_FILE_ERROR_MULTI = 24; //打开文件失败，流类型是复合流；
        public static readonly int PLAYM4_OPEN_FILE_ERROR_VIDEO = 25; //打开文件失败，流类型是视频流；
        public static readonly int PLAYM4_JPEG_COMPRESS_ERROR = 26; //JPEG压缩失败；
        public static readonly int PLAYM4_EXTRACT_NOT_SUPPORT = 27; //文件不支持；
        public static readonly int PLAYM4_EXTRACT_DATA_ERROR = 28; //数据错误；
        public static readonly int PLAYM4_SECRET_KEY_ERROR = 29; //解码密钥错误；
        public static readonly int PLAYM4_DECODE_KEYFRAME_ERROR = 30; //解码关键帧失败；
        public static readonly int PLAYM4_NEED_MORE_DATA = 31; //数据不足；
        public static readonly int PLAYM4_INVALID_PORT = 32; //无效端口号；
        public static readonly int PLAYM4_NOT_FIND = 33; //查找失败；
        public static readonly int PLAYM4_NEED_LARGER_BUFFER = 34; //需要更大的缓冲区；
        public static readonly int PLAYM4_FAIL_UNKNOWN = 99; //未知的错误；
        public static readonly int PLAYM4_FEC_ERR_ENABLEFAIL = 100; //鱼眼模块加载失败;
        public static readonly int PLAYM4_FEC_ERR_NOTENABLE = 101; //鱼眼模块没有加载;
        public static readonly int PLAYM4_FEC_ERR_NOSUBPORT = 102; //子端口没有分配;
        public static readonly int PLAYM4_FEC_ERR_PARAMNOTINIT = 103; //没有初始化对应端口的参数;
        public static readonly int PLAYM4_FEC_ERR_SUBPORTOVER = 104; //子端口已经用完;
        public static readonly int PLAYM4_FEC_ERR_EFFECTNOTSUPPORT = 105; //该安装方式下这种效果不支持;
        public static readonly int PLAYM4_FEC_ERR_INVALIDWND = 106; //非法的窗口;
        public static readonly int PLAYM4_FEC_ERR_PTZOVERFLOW = 107; //PTZ位置越界;
        public static readonly int PLAYM4_FEC_ERR_RADIUSINVALID = 108; //圆心参数非法;
        public static readonly int PLAYM4_FEC_ERR_UPDATENOTSUPPORT = 109; //指定的安装方式和矫正效果，该参数更新不支持;
        public static readonly int PLAYM4_FEC_ERR_NOPLAYPORT = 110; //播放库端口没有启用;
        public static readonly int PLAYM4_FEC_ERR_PARAMVALID = 111; //参数为空;
        public static readonly int PLAYM4_FEC_ERR_INVALIDPORT = 112; //非法子窗口;
        public static readonly int PLAYM4_FEC_ERR_PTZZOOMOVER = 113; //PTZ矫正范围越界;
        public static readonly int PLAYM4_FEC_ERR_OVERMAXPORT = 114; //矫正通道饱和，最大支持的矫正通道为四个;
        public static readonly int PLAYM4_FEC_ERR_ENABLED = 115; //该端口已经启用了鱼眼模块;
        public static readonly int PLAYM4_FEC_ERR_D3DACCENOTENABLE = 116; //D3D加速没有开启;
        public static readonly int PLAYM4_FEC_ERR_PLACETYPE = 117; //安装方式不正确；一个播放库port需要对应一种安装方式;        
        public static readonly int PLAYM4_FEC_ERR_CorrectType = 118; //矫正方式错误;
        public static readonly int PLAYM4_FEC_ERR_NULLWND = 119; //鱼眼窗口为NULL;
        public static readonly int PLAYM4_FEC_ERR_PARA = 120; //鱼眼参数错误;

        #endregion

        #region Display buffers
        public static readonly int MAX_DIS_FRAMES = 50; //播放缓冲最大值  
        public static readonly int MIN_DIS_FRAMES = 6; //播放缓冲最小值
        #endregion

        #region Locate by
        public static readonly int BY_FRAMENUM = 1;// 帧号
        public static readonly int BY_FRAMETIME = 2;// 时间
        #endregion

        #region Display type 
        public static readonly int DISPLAY_NORMAL = 1;// 正常分辨率数据送显卡显示
        public static readonly int DISPLAY_QUARTER = 2;// 1/4分辨率数据送显卡显示
        #endregion

        #region Timer type        
        public static readonly int TIMER_1 = 1; //一个进程中只能使用16个，定时比较准，画面流畅
        public static readonly int TIMER_2 = 2;// 使用数目没有限制，定时没有TIMER_1准
        #endregion

        #region BUFFER TYPE        
        public static readonly ushort BUF_VIDEO_SRC = 1;// 视频数据源缓冲区，缓冲解码之前视频数据，只对流模式有效，单位byte。
        public static readonly ushort BUF_AUDIO_SRC = 2;// 音频数据源缓冲区，缓冲解码之前音频数据，只对流模式有效, 单位byte。
        public static readonly ushort BUF_VIDEO_RENDER = 3;// 解码后视频数据缓冲区，单位帧数。
        public static readonly ushort BUF_AUDIO_RENDER = 4;// 解码后音频数据缓冲区，单位帧数，音频40ms数据定为一帧。
        #endregion

        // 以下宏定义用于HIK_MEDIAINFO结构
        public const int FOURCC_HKMI = 0x484B4D49;  // "HKMI" HIK_MEDIAINFO结构标记

        // 系统封装格式
        public const int SYSTEM_NULL = 0;// 没有系统层，纯音频流或视频流	
        public const int SYSTEM_HIK = 1;// 海康文件层
        public const int SYSTEM_MPEG2_PS = 2;// PS封装
        public const int SYSTEM_MPEG2_TS = 3;// TS封装
        public const int SYSTEM_RTP = 4;// rtp封装

        // 视频编码类型
        public const int VIDEO_NULL = 0;// 没有视频
        public const int VIDEO_H264 = 1;// 标准H.264和海康H.264都可以用这个定义
        public const int VIDEO_MPEG4 = 3;// 标准MPEG4

        // 音频编码类型
        public const int AUDIO_NULL = 0;// 没有音频
        public const int AUDIO_ADPCM = 4096;// ADPCM 
        public const int AUDIO_MPEG = 8192;// MPEG 系列音频，解码器能自适应各种MPEG音频

        // G系列音频
        public const int AUDIO_G711_U = 28944;
        public const int AUDIO_G711_A = 28945;
        public const int AUDIO_G722_1 = 29217;
        public const int AUDIO_G723_1 = 29233;
        public const int AUDIO_G726 = 29280;
        public const int AUDIO_G729 = 29328;
        #endregion

        #region HikPlayCtrl     

        [DllImport("/Hc/PlayCtrl.dll")]
        public static extern int PlayM4_GetSdkVersion();

        [DllImport("/Hc/PlayCtrl.dll")]
        public static extern bool PlayM4_GetPort(out int nPort);

        [DllImport("/Hc/PlayCtrl.dll")]
        public static extern bool PlayM4_SetDecCBStream(int nPort, int nStream);

        [DllImport("/Hc/PlayCtrl.dll")]
        public static extern bool PlayM4_FreePort(int nPort);

        [DllImport("/Hc/PlayCtrl.dll")]
        public static extern bool PlayM4_InitDDraw(IntPtr hWnd);

        [DllImport("/Hc/PlayCtrl.dll")]
        public static extern bool PlayM4_RealeseDDraw();

        [DllImport("/Hc/PlayCtrl.dll")]
        public static extern bool PlayM4_OpenFile(int nPort, string sFileName);

        [DllImport("/Hc/PlayCtrl.dll")]
        public static extern bool PlayM4_CloseFile(int nPort);

        [DllImport("/Hc/PlayCtrl.dll")]
        public static extern bool PlayM4_PlaySound(int nPort);

        [DllImport("/Hc/PlayCtrl.dll")]
        public static extern bool PlayM4_Play(int nPort, IntPtr hWnd);

        [DllImport("/Hc/PlayCtrl.dll")]
        public static extern bool PlayM4_Stop(int nPort);

        [DllImport("/Hc/PlayCtrl.dll")]
        public static extern bool PlayM4_Pause(int nPort, bool nPause);

        [DllImport("/Hc/PlayCtrl.dll")]
        public static extern bool PlayM4_Fast(int nPort);

        [DllImport("/Hc/PlayCtrl.dll")]
        public static extern bool PlayM4_Slow(int nPort);

        [DllImport("/Hc/PlayCtrl.dll")]
        public static extern bool PlayM4_SetPlayPos(int nPort, float fRelativePos);

        [DllImport("/Hc/PlayCtrl.dll")]
        public static extern int PlayM4_GetFileTime(int nPort);// 获取文件总时间 四舍五入后的文件总时间长度，单位：秒

        [DllImport("/Hc/PlayCtrl.dll")]
        public static extern int PlayM4_GetFileTotalFrames(int nPort);// 获取文件总帧数 成功返回文件总帧数

        [DllImport("/Hc/PlayCtrl.dll")]
        public static extern bool PlayM4_SetDecCallBack(int nPort, DecCBFun fDecCBFun);

        [DllImport("/Hc/PlayCtrl.dll")]
        public static extern bool PlayM4_SetDecCallBackMend(int nPort, DecCBFun fDecCBFun, int nUser);

        [DllImport("/Hc/PlayCtrl.dll")]
        public static extern bool PlayM4_SetFileEndCallback(int nPort, FileEndCallback fileEndCallback, int nUser);

        [DllImport("/Hc/PlayCtrl.dll")]
        public static extern bool PlayM4_SetDisplayCallBack(int nPort, DisplayCBFun fDisplayCBFun);
        #endregion
    }
}
